From e87b472143a1116a571f0b49c07afbbc33a88a84 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 23 Nov 2016 05:18:43 +0100 Subject: [PATCH] glcontext: Make begin/end_draw() paired This way, we can query the GL context's state via gdk_gl_context_is_drawing(). Use this function to make GL contexts as attached and grant them access to the front/backbuffer for rendering. All of this is still unused because GL drawing is still disabled. --- gdk/gdkglcontext.c | 84 +++++++++++++++++++++++++++++- gdk/gdkglcontextprivate.h | 3 ++ gdk/gdkwindow.c | 59 --------------------- gdk/mir/gdkmirdisplay.c | 2 +- gdk/wayland/gdkglcontext-wayland.c | 2 +- gdk/x11/gdkglcontext-x11.c | 22 ++++---- gdk/x11/gdkglcontext-x11.h | 3 +- 7 files changed, 102 insertions(+), 73 deletions(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 14157db057..2717f5d929 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -97,6 +97,7 @@ typedef struct { int gl_version; guint realized : 1; + guint is_drawing : 1; guint use_texture_rectangle : 1; guint has_gl_framebuffer_blit : 1; guint has_frame_terminator : 1; @@ -368,6 +369,78 @@ gdk_gl_context_init (GdkGLContext *self) priv->use_es = -1; } +/*< private > + * gdk_gl_context_is_drawing: + * @context: a #GdkGLContext + * + * Returns %TRUE if @context is in the process of drawing to its window. In such + * cases, it will have access to the window's backbuffer to render the new frame + * onto it. + * + * Returns: %TRUE if the context is between begin_frame() and end_frame() calls. + * + * Since: 3.90 + */ +gboolean +gdk_gl_context_is_drawing (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + return priv->is_drawing; +} + +/*< private > + * gdk_gl_context_begin_frame: + * @context: a #GdkGLContext + * @region: (inout): The clip region that needs to be repainted + * + * Sets up @context and @drawing for a new drawing. + * + * The @context is free to update @region to the size that actually needs to + * be repainted. Contexts that do not support partial blits for example may + * want to invalidate the whole window instead. + * + * The function does not clear the background. Clearing the backgroud is the + * job of the renderer. The contents of the backbuffer are undefined after this + * function call. + * + * Since: 3.90 + */ +void +gdk_gl_context_begin_frame (GdkGLContext *context, + cairo_region_t *region) +{ + GdkGLContextPrivate *priv, *shared_priv; + GdkGLContext *shared; + int ww, wh; + + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); + g_return_if_fail (region != NULL); + + priv = gdk_gl_context_get_instance_private (context); + priv->is_drawing = TRUE; + + shared = gdk_gl_context_get_shared_context (context); + shared_priv = gdk_gl_context_get_instance_private (shared); + shared_priv->is_drawing = TRUE; + + GDK_GL_CONTEXT_GET_CLASS (context)->begin_frame (context, region); + + ww = gdk_window_get_width (priv->window) * gdk_window_get_scale_factor (priv->window); + wh = gdk_window_get_height (priv->window) * gdk_window_get_scale_factor (priv->window); + + gdk_gl_context_make_current (shared); + + /* Initial setup */ + glClearColor (0.0f, 0.0f, 0.0f, 0.0f); + glDisable (GL_DEPTH_TEST); + glDisable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glViewport (0, 0, ww, wh); + +} + /*< private > * gdk_gl_context_end_frame: * @context: a #GdkGLContext @@ -387,15 +460,24 @@ gdk_gl_context_end_frame (GdkGLContext *context, cairo_region_t *painted, cairo_region_t *damage) { + GdkGLContextPrivate *priv, *shared_priv; + GdkGLContext *shared; + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); GDK_GL_CONTEXT_GET_CLASS (context)->end_frame (context, painted, damage); + + priv = gdk_gl_context_get_instance_private (context); + priv->is_drawing = FALSE; + + shared = gdk_gl_context_get_shared_context (context); + shared_priv = gdk_gl_context_get_instance_private (shared); + shared_priv->is_drawing = FALSE; } GdkGLContextPaintData * gdk_gl_context_get_paint_data (GdkGLContext *context) { - GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); if (priv->paint_data == NULL) diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index 24fd80ead3..3193e2d0d8 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -89,6 +89,9 @@ gboolean gdk_gl_context_use_texture_rectangle (GdkGLContext gboolean gdk_gl_context_has_framebuffer_blit (GdkGLContext *context); gboolean gdk_gl_context_has_frame_terminator (GdkGLContext *context); gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context); +gboolean gdk_gl_context_is_drawing (GdkGLContext *context); +void gdk_gl_context_begin_frame (GdkGLContext *context, + cairo_region_t *region); void gdk_gl_context_end_frame (GdkGLContext *context, cairo_region_t *painted, cairo_region_t *damage); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index f79cf4b2a7..d7e1d04ec8 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -2715,40 +2715,6 @@ gdk_window_begin_paint_internal (GdkWindow *window, surface_content = gdk_window_get_content (window); -#if 0 - if (window->current_paint.use_gl) - { - GdkGLContext *context; - - int ww = gdk_window_get_width (window) * gdk_window_get_scale_factor (window); - int wh = gdk_window_get_height (window) * gdk_window_get_scale_factor (window); - - context = gdk_window_get_paint_gl_context (window, NULL); - if (context == NULL) - { - g_warning ("gl rendering failed, context: %p", context); - window->current_paint.use_gl = FALSE; - } - else - { - gdk_gl_context_make_current (context); - /* With gl we always need a surface to combine the gl - drawing with the native drawing. */ - needs_surface = TRUE; - /* Also, we need the surface to include alpha */ - surface_content = CAIRO_CONTENT_COLOR_ALPHA; - - /* Initial setup */ - glClearColor (0.0f, 0.0f, 0.0f, 0.0f); - glDisable (GL_DEPTH_TEST); - glDisable(GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - glViewport (0, 0, ww, wh); - } - } -#endif - if (needs_surface) { window->current_paint.surface = gdk_window_create_similar_surface (window, @@ -2797,31 +2763,6 @@ gdk_window_end_paint_internal (GdkWindow *window) { cairo_surface_t *surface; -#if 0 - if (window->current_paint.use_gl) - { - cairo_region_t *opaque_region = cairo_region_copy (window->current_paint.region); - - gdk_gl_context_make_current (window->gl_paint_context); - - if (!cairo_region_is_empty (opaque_region)) - gdk_gl_texture_from_surface (window->current_paint.surface, - opaque_region); - if (!cairo_region_is_empty (window->current_paint.need_blend_region)) - { - glEnable(GL_BLEND); - gdk_gl_texture_from_surface (window->current_paint.surface, - window->current_paint.need_blend_region); - glDisable(GL_BLEND); - } - - cairo_region_destroy (opaque_region); - - gdk_gl_context_end_frame (window->gl_paint_context, - window->current_paint.region, - window->active_update_area); - } -#endif surface = gdk_window_ref_impl_surface (window); cr = cairo_create (surface); diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c index 0427dc3823..d5c4cd5f82 100644 --- a/gdk/mir/gdkmirdisplay.c +++ b/gdk/mir/gdkmirdisplay.c @@ -631,7 +631,7 @@ gdk_mir_display_make_gl_context_current (GdkDisplay *display, mir_context = GDK_MIR_GL_CONTEXT (context); window = gdk_gl_context_get_window (context); - if (mir_context->is_attached) + if (mir_context->is_attached || gdk_gl_context_is_drawing (context)) { egl_surface = _gdk_mir_window_get_egl_surface (window, mir_context->egl_config); diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c index c55e3070eb..1763ec7a18 100644 --- a/gdk/wayland/gdkglcontext-wayland.c +++ b/gdk/wayland/gdkglcontext-wayland.c @@ -464,7 +464,7 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay *display, context_wayland = GDK_WAYLAND_GL_CONTEXT (context); window = gdk_gl_context_get_window (context); - if (context_wayland->is_attached) + if (context_wayland->is_attached || gdk_gl_context_is_drawing (context)) egl_surface = gdk_wayland_window_get_egl_surface (window->impl_window, context_wayland->egl_config); else { diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c index 16ebb423ac..92aaaf16ad 100644 --- a/gdk/x11/gdkglcontext-x11.c +++ b/gdk/x11/gdkglcontext-x11.c @@ -175,7 +175,7 @@ gdk_x11_gl_context_end_frame (GdkGLContext *context, info = get_glx_drawable_info (window); - drawable = shared_x11->drawable; + drawable = shared_x11->attached_drawable; GDK_NOTE (OPENGL, g_message ("Flushing GLX buffers for drawable %lu (window: %lu), frame sync: %s", @@ -573,7 +573,6 @@ gdk_x11_gl_context_realize (GdkGLContext *context, GdkX11Display *display_x11; GdkDisplay *display; GdkX11GLContext *context_x11; - GLXWindow drawable; XVisualInfo *xvisinfo; Display *dpy; DrawableInfo *info; @@ -736,13 +735,10 @@ gdk_x11_gl_context_realize (GdkGLContext *context, XFree (xvisinfo); - if (context_x11->is_attached) - drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window); - else - drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin; + context_x11->attached_drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window); + context_x11->unattached_drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin; context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context); - context_x11->drawable = drawable; GDK_NOTE (OPENGL, g_message ("Realized GLX context[%p], %s", @@ -1248,6 +1244,7 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display, GdkX11GLContext *context_x11; Display *dpy = gdk_x11_display_get_xdisplay (display); gboolean do_frame_sync = FALSE; + GLXWindow drawable; if (context == NULL) { @@ -1263,11 +1260,16 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display, return FALSE; } + if (context_x11->is_attached || gdk_gl_context_is_drawing (context)) + drawable = context_x11->attached_drawable; + else + drawable = context_x11->unattached_drawable; + GDK_NOTE (OPENGL, - g_message ("Making GLX context current to drawable %lu", - (unsigned long) context_x11->drawable)); + g_message ("Making GLX context %p current to drawable %lu", + context, (unsigned long) drawable)); - if (!glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable, + if (!glXMakeContextCurrent (dpy, drawable, drawable, context_x11->glx_context)) { GDK_NOTE (OPENGL, diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h index c00834fa1d..192ee9e21f 100644 --- a/gdk/x11/gdkglcontext-x11.h +++ b/gdk/x11/gdkglcontext-x11.h @@ -42,7 +42,8 @@ struct _GdkX11GLContext GLXContext glx_context; GLXFBConfig glx_config; - GLXDrawable drawable; + GLXDrawable attached_drawable; + GLXDrawable unattached_drawable; guint is_attached : 1; guint is_direct : 1; -- 2.30.2